/*
	This file is part of PropExtractor.

	AliceDecrypt is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	AliceDecrypt is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with PropExtractor. If not, see <http://www.gnu.org/licenses/>.
*/

#include "PEAliceSoftZip.h"

#include "PETools.h"

namespace pe
{

	// ================================
	// Zip
	// ================================

	int AliceZipReadHeader(AliceZip* a_Target, PEFile* a_File)
	{
		a_Target->handle = a_File;

		char* lastslash = strrchr((char*)a_File->path, '\\');
		a_Target->workingdir = new char[lastslash - a_File->path + 1];
		strncpy(a_Target->workingdir, a_File->path, lastslash - a_File->path + 1);
		a_Target->workingdir[lastslash - a_File->path + 1] = 0;

		size_t read;
		a_Target->header = new AliceZipHeader;
		read = fread(a_Target->header, sizeof(AliceZipHeader), 1, a_Target->handle->handle);

		ALICE_DEBUG("Header: %s", a_Target->header->header);

		if (
			a_Target->header->header[0] != 'A' ||
			a_Target->header->header[1] != 'A' ||
			a_Target->header->header[2] != 'R'
		)
		{
			return -1;
		}

		a_Target->files_total = a_Target->header->number_of_files;
		a_Target->files = new AliceZipFile[a_Target->files_total];

		char temp[256];
		AliceZipFile* dst = a_Target->files;
		for (unsigned int i = 0; i < a_Target->files_total; i++)
		{
			dst->header = new AliceZipFileHeader;
			read = fread(dst->header, sizeof(AliceZipFileHeader), 1, a_Target->handle->handle);

			memset(temp, 0, 256);
			int j = 0;
			do 
			{
				fread(&temp[j], 1, 1, a_Target->handle->handle);
			} 
			while (temp[j++] != 0 && j < 256);

			dst->path = new char[j];
			strcpy(dst->path, temp);

			dst++;
		}

		return 0;
	}

	int AliceZipOpenFile(PEFile* a_Target, AliceZip* a_Zip, unsigned int a_Index)
	{
		// open another handle to the zip...

		a_Target->handle = fopen(a_Zip->handle->path, "rb");
		if (!a_Target->handle) { return -1; }

		// ... but with an offset

		fseek(a_Target->handle, a_Zip->files[a_Index].header->offset, SEEK_SET);

		a_Target->path = new char[strlen(a_Zip->files[a_Index].path) + 1];
		strcpy(a_Target->path, a_Zip->files[a_Index].path);

		return 0;
	}

	int AliceZipExtractFile(AliceZip* a_Zip, unsigned int a_Index, const char* a_Pattern)
	{
		char filepath[_MAX_PATH];
		strcpy(filepath, a_Zip->workingdir);
		strcat(filepath, a_Zip->files[a_Index].path);

		/*char path[_MAX_PATH];
		size_t path_len;
		if (a_Pattern)
		{
			GetPatternedPath(path, &path_len, a_Pattern, &read, a_Zip, a_Index);
		}
		else
		{
			strcpy(path, a_ZipFile->workingdir);
			strcat(path, read.path);
		}*/
		
		if (CheckDirectory(filepath) != 0) { return -1; }

		FILE* handle = fopen(filepath, "w+b");
		if (!handle) { return -1; }
		fseek(a_Zip->handle->handle, a_Zip->files[a_Index].header->offset, SEEK_SET);

		size_t filesize;
		if (a_Index == a_Zip->files_total - 1)
		{
			size_t pos_curr = ftell(a_Zip->handle->handle);
			fseek(a_Zip->handle->handle, 0, SEEK_END);
			size_t totalsize = ftell(a_Zip->handle->handle);
			fseek(a_Zip->handle->handle, pos_curr, SEEK_SET);

			filesize = totalsize - a_Zip->files[a_Index].header->offset;
		}
		else
		{
			filesize = a_Zip->files[a_Index + 1].header->offset - a_Zip->files[a_Index].header->offset;
		}

		byte* temp = new byte[filesize];
		fread(temp, 1, filesize, a_Zip->handle->handle);

		fwrite(temp, filesize, 1, handle);

		fclose(handle);

		delete temp;

		return 0;
	}

}; // namespace pe